// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

#include "HotPakerTool.h"
#include "HotPakerToolStyle.h"
#include "HotPakerToolCommands.h"
#include "Misc/MessageDialog.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "ContentBrowserModule.h"
#include "ContentBrowserDelegates.h"
#include "LevelEditor.h"
#include "HotPakerFileLib.h"
#include "Widgets/Settings/SCookDialogue.h"
#include "AssetRegistryModule.h"

#include "ILauncherServicesModule.h"
#include "ITargetDeviceServicesModule.h"

#include "Models/HotPakerModel.h"
#include "Widgets/Settings/SHotPakerSettings.h"

static const FName CookDialogueTabName("CookDialogue");
static const FName HotPakerToolTabName("HotPakerTool");

#define LOCTEXT_NAMESPACE "FHotPakerToolModule"

void FHotPakerToolModule::StartupModule()
{
	// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module

	FHotPakerToolStyle::Initialize();
	FHotPakerToolStyle::ReloadTextures();

	FHotPakerToolCommands::Register();

	PluginCommands = MakeShareable(new FUICommandList);

	PluginCommands->MapAction(
		FHotPakerToolCommands::Get().PluginAction,
		FExecuteAction::CreateRaw(this, &FHotPakerToolModule::PluginButtonClicked),
		FCanExecuteAction());

	FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");

	{
		TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender());
		MenuExtender->AddMenuExtension("WindowLayout", EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &FHotPakerToolModule::AddMenuExtension));

		LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
	}

	{
		TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
		ToolbarExtender->AddToolBarExtension("Settings", EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FHotPakerToolModule::AddToolbarExtension));

		LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender);
	}

	FGlobalTabmanager::Get()->RegisterNomadTabSpawner(HotPakerToolTabName, FOnSpawnTab::CreateRaw(this, &FHotPakerToolModule::OnSpawnHotPakerTool))
		.SetDisplayName(LOCTEXT("FHotPakerToolTitle", "HotPakerTool"))
		.SetMenuType(ETabSpawnerMenuType::Hidden);


	FGlobalTabmanager::Get()->RegisterNomadTabSpawner(CookDialogueTabName, FOnSpawnTab::CreateRaw(this, &FHotPakerToolModule::OnSpawnCookDialouge))
		.SetDisplayName(LOCTEXT("FCookDialogueTitle", "CookDialouge"))
		.SetMenuType(ETabSpawnerMenuType::Hidden);


	AddAssetCookMenuExtender();

	AddPathCookMenuExtender();
}

void FHotPakerToolModule::ShutdownModule()
{
	// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
	// we call this function before unloading the module.
	FHotPakerToolStyle::Shutdown();

	FHotPakerToolCommands::Unregister();
}

void FHotPakerToolModule::PluginButtonClicked()
{
	TSharedRef<SDockTab> DockTab = FGlobalTabmanager::Get()->InvokeTab(HotPakerToolTabName);
}

void FHotPakerToolModule::AddMenuExtension(FMenuBuilder& Builder)
{
	Builder.AddMenuEntry(FHotPakerToolCommands::Get().PluginAction);
}

void FHotPakerToolModule::AddAssetCookMenuExtender()
{
	FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
	ContentBrowserModule.GetAllAssetViewContextMenuExtenders().Add(FContentBrowserMenuExtender_SelectedAssets::CreateRaw(this, &FHotPakerToolModule::GetAssetCookMenuExtender));
}

TSharedRef<FExtender> FHotPakerToolModule::GetAssetCookMenuExtender(const TArray<FAssetData>& SelectedAssets)
{
	TSharedRef<FExtender> Extender = MakeShareable(new FExtender);

	FText AssetName = SelectedAssets.Num() > 0 ? FText::Format(LOCTEXT("AssetNameSingular", "\"{0}\""), FText::FromName(SelectedAssets[0].AssetName)) : LOCTEXT("AssetNamePlural", "Asset");

	Extender->AddMenuExtension(
		"CommonAssetActions",
		EExtensionHook::After,
		TSharedPtr<FUICommandList>(),
		FMenuExtensionDelegate::CreateLambda([this, SelectedAssets, AssetName](FMenuBuilder& MenuBuilder)
	{
		MenuBuilder.AddMenuEntry(
			FText::Format(LOCTEXT("CookCommand", "Cook {0}"), AssetName),
			LOCTEXT("CookCommand", "Cook the selected asset. Supports all asset."),
			FSlateIcon(),
			FUIAction(FExecuteAction::CreateRaw(this, &FHotPakerToolModule::OpenAssetCookDialouge, SelectedAssets)));
	}));

	return Extender;
}

void FHotPakerToolModule::OpenAssetCookDialouge(TArray<FAssetData> SelectedAssets)
{
	if (SelectedAssets.Num() == 0)
		return;

	TSharedRef<SDockTab> DockTab = FGlobalTabmanager::Get()->InvokeTab(CookDialogueTabName);
	TSharedRef<SCookDialogue> CookDialogue = StaticCastSharedRef<SCookDialogue>(DockTab->GetContent());
	CookDialogue->CookAssets(SelectedAssets);
}

void FHotPakerToolModule::AddPathCookMenuExtender()
{
	FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));
	ContentBrowserModule.GetAllPathViewContextMenuExtenders().Add(FContentBrowserMenuExtender_SelectedPaths::CreateRaw(this, &FHotPakerToolModule::GetPathCookMenuExtender));
}

TSharedRef<FExtender> FHotPakerToolModule::GetPathCookMenuExtender(const TArray<FString>& SelectedPaths)
{
	TSharedRef<FExtender> Extender = MakeShareable(new FExtender);

	FText PathName = SelectedPaths.Num() > 0 ? FText::Format(LOCTEXT("PathNameSingular", "\"{0}\""), FText::FromString(SelectedPaths[0])) : LOCTEXT("PathNamePlural", "Path");

	Extender->AddMenuExtension(
		"PathViewFolderOptions",
		EExtensionHook::After,
		TSharedPtr<FUICommandList>(),
		FMenuExtensionDelegate::CreateLambda([this, SelectedPaths, PathName](FMenuBuilder& MenuBuilder)
	{
		MenuBuilder.AddMenuEntry(
			FText::Format(LOCTEXT("CookCommand", "Cook {0}"), PathName),
			LOCTEXT("CookCommand", "Cook the selected path. Supports all path."),
			FSlateIcon(),
			FUIAction(FExecuteAction::CreateRaw(this, &FHotPakerToolModule::OpenPathCookDialouge, SelectedPaths)));
	}));

	return Extender;
}

void FHotPakerToolModule::OpenPathCookDialouge(TArray<FString> SelectedPaths)
{
	if (SelectedPaths.Num() == 0)
		return;

	TSharedRef<SDockTab> DockTab = FGlobalTabmanager::Get()->InvokeTab(CookDialogueTabName);
	TSharedRef<SCookDialogue> CookDialogue = StaticCastSharedRef<SCookDialogue>(DockTab->GetContent());
	CookDialogue->CookPaths(SelectedPaths);
}


TSharedRef<class SDockTab> FHotPakerToolModule::OnSpawnCookDialouge(const class FSpawnTabArgs& SpawnTabArgs)
{
	return SNew(SDockTab)
		.TabRole(ETabRole::NomadTab)
		[
			// Put your tab content here!
			SNew(SCookDialogue)
		];
}

TSharedRef<class SDockTab> FHotPakerToolModule::OnSpawnHotPakerTool(const class FSpawnTabArgs& SpawnTabArgs)
{
	const TSharedRef<SDockTab> DockTab = SNew(SDockTab)
		.Icon(FEditorStyle::GetBrush("Launcher.TabIcon"))
		.TabRole(ETabRole::NomadTab);

	ILauncherServicesModule& ProjectLauncherServicesModule = FModuleManager::LoadModuleChecked<ILauncherServicesModule>("LauncherServices");
	//ITargetDeviceServicesModule& TargetDeviceServicesModule = FModuleManager::LoadModuleChecked<ITargetDeviceServicesModule>("TargetDeviceServices");

	TSharedRef<FHotPakerModel> Model = MakeShareable(new FHotPakerModel(
		ProjectLauncherServicesModule.GetProfileManager()
	));

	DockTab->SetContent(SNew(SHotPakerSettings, Model));

	return DockTab;
}

void FHotPakerToolModule::AddToolbarExtension(FToolBarBuilder& Builder)
{
	Builder.AddToolBarButton(FHotPakerToolCommands::Get().PluginAction);
}

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(FHotPakerToolModule, HotPakerTool)